package com.egg.basic.controller.web;

import cn.hutool.core.util.ObjectUtil;
import com.egg.basic.service.SwaggerToTemplateService;
import com.egg.common.core.model.controller.WebController;
import com.egg.common.core.model.response.ResponseData;
import com.egg.common.util.HttpServletUtil;
import com.egg.common.util.IpUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring5.SpringTemplateEngine;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Map;

/**
 * @author east
 */
@Slf4j
@Api(tags = WebController.API_PREFIX + "文档中心")
@RestController
@RequestMapping("/swagger")
public class WebSwaggerController extends WebController {


    @Autowired
    private SwaggerToTemplateService swaggerToTemplateService;
    @Autowired
    private SpringTemplateEngine springTemplateEngine;


    /**
     * 转 WORD 默认文件名
     */
    private String wordFileName = "toWord";
    /**
     * 转 HTML 默认文件名
     */
    private String htmlFileName = "toHtml";


    @ApiOperation(value = "swagger 服务地址")
    @GetMapping("/server")
    public ResponseData<String> monitorAdminServer() {
        String serverIp = IpUtil.serverIp();
        return ResponseData.success("http://" + serverIp + ":9527/doc.html");
    }

    @ApiOperation(value = "将 swagger 文档转换成 html 文档")
    @GetMapping(value = "/url/html", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
    public void urlToHtml(
            Model model
            , @ApiParam(value = "服务器:端口号/v2/api-docs url地址", required = true) @RequestParam(value = "url") String url
    ) {
        generateModelData(model, url, 1);
        writeContentToResponse(model, ".html", htmlFileName);
    }

    private void generateModelData(Model model, String url, Integer download) {
        if (ObjectUtil.isEmpty(url)) {
            return;
        }
        Map<String, Object> result = swaggerToTemplateService.tableList(url);
        model.addAttribute("url", url);
        model.addAttribute("download", download);
        model.addAllAttributes(result);
    }

    @ApiOperation(value = "将 swagger 文档一键下载为 doc 文档")
    @GetMapping(value = "/url/word", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
    public void urlToWord(
            Model model
            , @ApiParam(value = "服务器:端口号/v2/api-docs url地址", required = true) @RequestParam(value = "url") String url
    ) {
        generateModelData(model, url, 0);
        writeContentToResponse(model, ".doc", wordFileName);
    }

    private void writeContentToResponse(Model model, String suffix, String fileName) {
        HttpServletResponse response = HttpServletUtil.getHttpServletResponse();
        if (null == response) {
            return;
        }
        Context context = new Context();
        context.setVariables(model.asMap());
        String content = springTemplateEngine.process("word", context);
        response.setContentType("application/octet-stream;charset=utf-8");
        response.setCharacterEncoding("utf-8");
        try (
                //语法糖: try块退出时，会自动调用.close()方法，关闭资源。
                BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream())
        ) {
            response.setHeader(HttpHeaders.CONTENT_DISPOSITION, String.format("attachment;filename=%s", URLEncoder.encode(fileName + suffix, "utf-8")));
            byte[] bytes = content.getBytes();
            bos.write(bytes, 0, bytes.length);
            bos.flush();
        } catch (IOException e) {
            log.error("", e);
        }
    }

    @ApiOperation(value = "将 swagger json文件转换成 word文档并下载")
    @PostMapping(value = "/file/word", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
    public void fileToWord(
            Model model
            , @ApiParam(value = "swagger json file", required = true) @Valid @RequestPart("jsonFile") MultipartFile jsonFile
    ) {
        generateModelData(model, jsonFile);
        writeContentToResponse(model, ".doc", wordFileName);
    }

    @ApiOperation(value = "将 swagger json字符串转换成 word文档并下载")
    @PostMapping(value = "/str/word", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
    public void strToWord(
            Model model
            , @ApiParam(value = "swagger json string", required = true) @Valid @RequestParam("jsonStr") String jsonStr
    ) {
        generateModelData(model, jsonStr);
        writeContentToResponse(model, ".doc", wordFileName);
    }

    private void generateModelData(Model model, String jsonStr) {
        Map<String, Object> result = swaggerToTemplateService.tableListFromString(jsonStr);
        model.addAttribute("url", "http://");
        model.addAttribute("download", 0);
        model.addAllAttributes(result);
    }

    private void generateModelData(Model model, MultipartFile jsonFile) {
        Map<String, Object> result = swaggerToTemplateService.tableList(jsonFile);
        wordFileName = jsonFile.getOriginalFilename();
        if (wordFileName != null) {
            wordFileName = wordFileName.replaceAll(".json", "");
        } else {
            wordFileName = "toWord";
        }
        model.addAttribute("url", "http://");
        model.addAttribute("download", 0);
        model.addAllAttributes(result);
    }


}
